/**
 * 主要用于判断一个数组是否每个元素都是空
 * 应用场景：创建问卷模板时，确保每一个选项都有值
 */
export function isNil(v) {
  if (typeof v === 'undefined') return true
  if (typeof v === 'string' && v.trim() === '') return true
  if (v instanceof Array && v.length === 0) return true
  if (v instanceof Array && v.some(isNil)) return true
  if (v instanceof Array) return false // 此时还是数组就代表通过了 length 和 some 的判断
  if (typeof v === 'object' && isNil(Object.values(v))) return true
  // NOTE: 可能会有未考虑到的情况
  return false
}

export const isNotNil = v => !isNil(v)

// 数组的 findIndex 进行封装处理, 增加: 数组中不存在元素时返回 -1
export function findIndex(array, predicate) {
  if (array.length === 0) return -1
  return array.findIndex(predicate)
}

export function once(fn) {
  return function (...args) {
    if (fn) {
      const result = fn.apply(this, args)
      fn = null
      return result
    }
  }
}

// 获取路径上的参数, 现在只有在填写问卷时会想要获取该参数, 所以 i 默认值直接设置为 1 就可以了
export function getPath(i = 1) {
  const pathName = window.location.pathname // 例如 /fill-in/123
  const path = pathName.split('/').filter(v => !!v) // 过滤空字符
  return path[i]
}

// NOTE: 此处进行的测试不多, 有可能发生内存泄漏问题
export function hasSameKey(obj1, obj2) {
  // 原则, 应该对 true 的返回谨慎
  if (typeof obj1 === 'string' && typeof obj2 === 'string') return true
  if (typeof obj1 === 'number' && typeof obj2 === 'number') return true
  if (typeof obj1 === 'boolean' && typeof obj2 === 'boolean') return true
  if (typeof obj1 === 'null' && typeof obj2 === 'null') return true
  if (typeof obj1 === 'undefined' && typeof obj2 === 'undefined') return true

  if (obj1 instanceof Array && obj2 instanceof Array) {
    // 对数组, 先满足长度相同, 然后比较元素, 如果元素是对象或者数组, 则递归比较
    if (obj1.length !== obj2.length) return false

    for (let i = 0; i < obj1.length; i++) {
      if (!hasSameKey(obj1[i], obj2[i])) return false
    }

    return true
  }

  if (!(obj1 instanceof Array) && !(obj2 instanceof Array)) {
    const key1 = Object.keys(obj1)
    const key2 = Object.keys(obj2)
    if (key1.length !== key2.length) return false
    for (let i = 0; i < key1.length; i++) {
      if (!obj2.hasOwnProperty(key1[i])) return false
      if (!hasSameKey(obj1[key1[i]], obj2[key1[i]])) return false
    }
    return true
  }

  return false
}

// YYYY/MM/DD HH:MM
export function formatTime(time) {
  if (typeof time !== 'number' ) time = Number.parseInt(time)
  const date = new Date(time)
  return (
    date.getFullYear() +
    '/' +
    formatNum(date.getMonth() + 1) +
    '/' +
    formatNum(date.getDate()) +
    ' ' +
    formatNum(date.getHours()) +
    ':' +
    formatNum(date.getMinutes())
  )
}

export function serialLetter(num) {
  if (num < 26) return String.fromCharCode(65 + num)
  let s = String.fromCharCode(65 + (num % 26))
  while (num != 0) {
    num = Number.parseInt(num / 25)
    s = 'A' + s
  }
  return s
}

// 对 num 进行前置补零, 确保 num 占 digit 位
export function formatNum(num, digit = 2) {
  const _digit = digit
  if (digit > 5) return num
  while (digit-- > 0) num = '0' + num
  return num.substring(num.length - _digit)
}